#include "menu.h"

/* A full-screen SMK player */

// Dependency on libsmacker
#include <Smacker/smacker.h>

// Send in the externs
extern GLuint cursor_list;
extern struct cfg_struct *cfg;
extern GLfloat aspect;
extern int mx, my;

static Uint32 menu_next_frame(Uint32 interval, void *param)
{
    SDL_Event event;
    SDL_UserEvent userevent;

    /* In this example, our callback pushes an SDL_USEREVENT event
	 into the queue, and causes ourself to be called again at the
	 same interval: */

    userevent.type = SDL_USEREVENT;
    userevent.code = 0;
    userevent.data1 = NULL;
    userevent.data2 = NULL;

    event.type = SDL_USEREVENT;
    event.user = userevent;

    SDL_PushEvent(&event);
    return(interval);
}

int menu_main()
{
    // set to 0 to run.  set to non-zero to exit and change gamestate
	int done = 0,i;

    // Video
    smk s;
	SDL_TimerID frame_timer;

	// Integer which holds the current frame texture
	SDL_Surface *frame = NULL;
    GLuint frame_tex;
	// Other UI textures
	GLuint menu_tex[5];
	// Screen positioning (letterbox / pillarbox)
	GLuint xoffset, yoffset;
	float scale_x, scale_y, unscale_x, unscale_y;

    /* Go open the SMK file. */
    if (!(s = smk_open("data/video/menusky.smk",SMK_MODE_MEMORY)))
    {
        /* Unable to load SMK file. Rats. */
        printf("WARNING: Unable to load data/video/menusky.smk.\n");
		return GAMESTATE_ERROR;
    }

    smk_enable_palette(s,1);
    smk_enable_video(s,1);

	smk_first(s);

	/* Set up all the textures we'll need for this screen. */
    frame = tex_from_smkframe(smk_get_palette(s),smk_get_video(s),smk_info_video_w(s),smk_info_video_h(s));
    if (frame == NULL)
    {
        fprintf(stderr,"WARNING: tex_from_smkframe returned NULL.\n");
        done = GAMESTATE_ERROR;
    } else {
        frame_tex = build_texture (frame, GL_LINEAR);
        SDL_FreeSurface(frame);
    }
	menu_tex[0] = load_texture_colorkey("main1",GL_LINEAR,0,255,255);
	menu_tex[1] = load_texture_colorkey("main2",GL_LINEAR,0,255,255);
	menu_tex[2] = load_texture_colorkey("main3",GL_LINEAR,0,255,255);
	menu_tex[3] = load_texture("main4",GL_LINEAR);
	menu_tex[4] = load_texture("main5",GL_LINEAR);

	/* Perform a conversion for scaled items to screen coords. */
    float movie_aspect = ((float)smk_info_video_w(s)) / ((float)smk_info_video_h(s));
    if (movie_aspect > aspect) // 16:9 movie on narrow screen: match W, scale H
    {
		scale_x = (float)smk_info_video_w(s);
		scale_y = (float)smk_info_video_w(s) / aspect;
		xoffset = 0;
		yoffset = ((((float)smk_info_video_w(s) / aspect) - (float)smk_info_video_h(s)) / 2) + .5;
    }
    else // 4:3 movie on wider screen: match H, scale W
    {
		scale_x = aspect * (float)smk_info_video_h(s);
		scale_y = (float)smk_info_video_h(s);
		xoffset = ((((float)smk_info_video_h(s) * aspect) - (float)smk_info_video_w(s)) / 2) + .5;
		yoffset = 0;
    }
	unscale_x = (float)cfg_get_int(cfg,"SCREEN_X");
	unscale_y = (float)cfg_get_int(cfg,"SCREEN_Y");

	GLuint quad_list = glGenLists(1);
	glNewList(quad_list, GL_COMPILE);
		glBox(xoffset,yoffset,smk_info_video_w(s),smk_info_video_h(s),frame_tex);
	glEndList();

    /* draws the little UI widget */
    GLuint menu_list = glGenLists(1);
	glNewList(menu_list, GL_COMPILE);
		glBox(xoffset + 2,yoffset + 29, 425, 414, menu_tex[0]);
		glBox(xoffset+289,yoffset,81,29,menu_tex[1]);
		glBox(xoffset + 427, yoffset + 315,213,165,menu_tex[2]);
    glEndList();

	/* Load MUSIC */
	Mix_Music *menu_music = load_music("menuback");
	if(!menu_music) {
		printf("music_load(\"menuback\"): %s\n", Mix_GetError());
	} else {
		if(Mix_PlayMusic(menu_music, -1)==-1) {
			printf("Mix_PlayMusic: %s\n", Mix_GetError());
		}
	}

	Mix_Chunk *menu_click = load_wave("menu");
	if(!menu_click) {
		printf("music_load(\"menuclick\"): %s\n", Mix_GetError());
	}

	unsigned char highlighted = 0;

	// Start the video timer
	frame_timer = SDL_AddTimer((Uint32)((1000.0f / smk_info_fps(s)) + 0.5f), menu_next_frame, NULL);

	SDL_GetMouseState(&mx, &my);

	SDL_Event event;

	unsigned char dirty = 1;
	int trans_x, trans_y;

	while (!done)
	{
		/* Check for events */
        /* Keypress skips to video 2 */
		while (SDL_PollEvent (&event))
		{
			switch (event.type)
			{
				case SDL_USEREVENT:
					dirty = 1;
					if (smk_next(s) == SMK_DONE)
					{
						// movie over, out of frames
						smk_first(s);
					}

					frame = tex_from_smkframe(smk_get_palette(s),smk_get_video(s),smk_info_video_w(s),smk_info_video_h(s));
					if (frame == NULL)
					{
						fprintf(stderr,"WARNING: tex_from_smkframe returned NULL.\n");
						done = GAMESTATE_ERROR;
					} else {
						glBindTexture(GL_TEXTURE_2D,frame_tex);
						rebuild_texture (frame_tex, frame);
						SDL_FreeSurface(frame);
					}
					break;
				case SDL_KEYUP:
					if (event.key.keysym.sym == SDLK_ESCAPE)
						done = GAMESTATE_EXIT;
					//                    done = next_gamestate;
					break;
				case SDL_MOUSEMOTION:
					// mouse move = cursor redraw
					dirty = 1;

					mx = event.motion.x;
					my = event.motion.y;

					// convert x / y to scale-coords
					trans_x = (event.motion.x * scale_x / unscale_x) - xoffset;
					trans_y = (event.motion.y * scale_y / unscale_y) - yoffset;

					if (trans_x > 34 && trans_x < 396)
					{
						if (trans_y > 59 && trans_y < 365)
						{
							i = (trans_y - 60) / 65;
						}
					} else {
					    i = 5;
					}

                    /* Design change: original game always had something highlighted.
                         Now, you must be in the box.  Outside that puts you in highlight 5, which means
                         you go to Credits on click instead. */
					if (i != highlighted)
					{
					    Mix_PlayChannel(-1,menu_click,0);
					    highlighted = i;
					}

					break;
				case SDL_MOUSEBUTTONUP:
					if (highlighted == 0) done = GAMESTATE_CAREER;
					else if (highlighted == 1) done = GAMESTATE_USER;
					else if (highlighted == 2) done = GAMESTATE_LOAD;
					else if (highlighted == 3) done = GAMESTATE_MULTI;
					else if (highlighted == 4) done = GAMESTATE_EXIT;
					else done = GAMESTATE_CREDITS;
					break;
				case SDL_QUIT:
                    done = GAMESTATE_EXIT;
					break;
				default:
					break;
			}
		}

		if (dirty) {
			/* Nuke everything */
			glClear(GL_COLOR_BUFFER_BIT);

			/* Put us into GLOrtho mode */
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			/* Match movie resolution */
			/* This is to draw "scaled" UI elements */
			glOrtho(0.0f,scale_x,scale_y,0.0f,-1.0f,1.0f);

			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();

			glCallList(quad_list);

			glEnable(GL_BLEND);
			glCallList(menu_list);
			glDisable(GL_BLEND);


			// Overlay 3d buttons.
			glBindTexture(GL_TEXTURE_2D,menu_tex[4]);
			for (i = 0; i < 5; i ++)
			{
				if (i != highlighted)
				{
					float ymin = i * 64.0f;
					float ymax = ymin + 64.0f;
					if (ymax > 297) ymax = 297;

					glBegin(GL_QUADS);
						glTexCoord2f(0,ymin / 512);
						glVertex2i(xoffset + 35, yoffset + 63 + ymin);
						glTexCoord2f(0,ymax / 512);
						glVertex2i(xoffset + 35, yoffset + 63 + ymax);
						glTexCoord2f(39.0f / 128,ymax / 512);
			//  Yes, the UI has graphics issues: it's 2 pixels too thin.
			//  Fixed here.
						glVertex2i(xoffset + 35 + 39 + 2, yoffset + 63 + ymax);
						glTexCoord2f(39.0f / 128,ymin / 512);
			//  And here.
						glVertex2i(xoffset + 35 + 39 + 2, yoffset + 63 + ymin);
					glEnd();
				}
			}

			// Overlay end-bluelight boxes
			glBindTexture(GL_TEXTURE_2D,menu_tex[3]);
			for (i = 0; i < 5; i ++)
			{
				if (i != highlighted)
				{
					float ymin = i * 65.0f - 13.0f;
					float ymax = ymin + 65.0f;
					if (ymin < 0) ymin = 0;

					glBegin(GL_QUADS);
						glTexCoord2f(0,ymin / 512);
						glVertex2i(xoffset + 336, yoffset + 60 + ymin);
						glTexCoord2f(0,ymax / 512);
						glVertex2i(xoffset + 336, yoffset + 60 + ymax);
						glTexCoord2f(60.0f / 128,ymax / 512);
						glVertex2i(xoffset + 336 + 60, yoffset + 60 + ymax);
						glTexCoord2f(60.0f / 128,ymin / 512);
						glVertex2i(xoffset + 336 + 60, yoffset + 60 + ymin);
					glEnd();
				}
			}

			/* Flip back into GLOrtho mode */
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			/* Match screen resolution */
			/* This is to draw "unscaled" UI elements */
			glOrtho(0.0f,unscale_x,unscale_y,0.0f,-1.0f,1.0f);

			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();

			glEnable(GL_ALPHA_TEST);
			glPushMatrix();
				glTranslatef(mx,my,0);
				glCallList(cursor_list);
			glPopMatrix();
			glDisable(GL_ALPHA_TEST);

			SDL_GL_SwapBuffers();

			dirty = 0;
		}

		/* Don't run too fast */
		SDL_Delay (1);
	}

	/* shutdown frame timer */
	SDL_RemoveTimer(frame_timer);

	/* end music */
	if (menu_click != NULL) { Mix_FreeChunk(menu_click); }
	if (menu_music != NULL) { Mix_HaltMusic(); Mix_FreeMusic(menu_music); }

    glDeleteLists(quad_list, 1);

	glDeleteTextures( 5, menu_tex);
	glDeleteTextures( 1, &frame_tex );

	smk_close(s);

	return done;
}

